#      SJ编程规范
# 命名：
#    1. 见名思意，变量的名字必须准确反映它的含义和内容
#    2. 遵循当前语言的变量命名规则
#    3. 不要对不同使用目的的变量使用同一个变量名
#    4. 同个项目不要使用不同名称表述同个东西
#    5. 函数/方法 使用动词+名词组合，其它使用名词组合
# 设计原则：
#    1. KISS原则： Keep it simple and stupid !
#    2. SOLID原则： S: 单一职责 O: 开闭原则 L: 迪米特法则 I: 接口隔离原则 D: 依赖倒置原则
#
import logging
from flask import request, Blueprint
from flask_restful import Resource
from flask_jwt_extended import jwt_required, current_user
from sqlalchemy import text

from {{cookiecutter.app_name}}.commons import db_util
from {{cookiecutter.app_name}}.commons.constants import return_code
from {{cookiecutter.app_name}}.models.{{title_lower}} import {{ title_lower | to_pascal_case }}
from {{cookiecutter.app_name}}.api.schemas.{{title_lower}} import {{ title_lower | to_pascal_case }}Schema
from {{cookiecutter.app_name}}.extensions import db
from {{cookiecutter.app_name}}.commons.pagination import paginate
{%- if cookiecutter.use_excel == "yes" %}
import flask_excel as excel
{%- endif %}

logger = logging.getLogger(__name__)

{{title_lower}}_bp = Blueprint('{{title_lower}}', __name__, url_prefix='/api/v1')


class {{title_lower | to_pascal_case }}Resource(Resource):
    """{{tb_obj.comment or tb_obj.info}} resource

    ---
    get:
      tags:
        - api
      parameters:
        - in: path
          name: id
          schema:
            type: string
      responses:
        200:
          content:
            application/json:
              schema:
                type: object
                properties:
                  {{title_lower}}: {{title_lower | to_pascal_case}}Schema
        404:
          description: {{title_lower}} does not exists
    put:
      tags:
        - api
      parameters:
        - in: path
          name: id
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              {{title_lower | to_pascal_case }}Schema
      responses:
        200:
          content:
            application/json:
              schema:
                type: object
                properties:
                  msg:
                    type: string
                    example: {{title_lower}} updated
                  {{title_lower}}: {{title_lower | to_pascal_case}}Schema
        404:
          description: {{title_lower}} not exists
    delete:
      tags:
        - api
      parameters:
        - in: path
          name: id
          schema:
            type: string
      responses:
        200:
          content:
            application/json:
              schema:
                type: object
                properties:
                  msg:
                    type: string
                    example: {{title_lower}} deleted
        404:
          description: {{title_lower}} does not exists
    """
    method_decorators = [jwt_required]

    def get(self, id):
        schema = {{title_lower | to_pascal_case }}Schema(unknown=True,)
        {{title_lower}} = {{title_lower | to_pascal_case }}.query.get(id)
        if {{title_lower}}:
            ret = schema.dump({{title_lower}}.__dict__)
            return return_code.SUCCESS.set_data(ret).d, 200
        else:
            return return_code.NOT_FOUND.d, 200

    def put(self, id):
        session = db.session
        schema = {{title_lower | to_pascal_case }}Schema(unknown=True, partial=True)
        # {{title_lower}} = {{title_lower | to_pascal_case }}.query.get(id)
        {{title_lower}} = schema.load(request.json)
        {{title_lower}}.updated_by = current_user.id
        session.merge({{title_lower}})
        session.flush()
        return return_code.SUCCESS.d, 200

    def post(self, id):
        schema = {{title_lower | to_pascal_case }}Schema(unknown=True)
        {{title_lower}} = schema.load(request.json)
        {{title_lower}}.updated_by = current_user.id
        db.session.add({{title_lower}})
        db.session.flush()

        return return_code.SUCCESS.d, 200

    def delete(self, id):
        {{title_lower}} = {{title_lower | to_pascal_case }}.query.get(id)
        if {{title_lower}}:
            db.session.delete({{title_lower}})
            db.session.flush()
        else:
            return return_code.NOT_FOUND.d, 200

        return return_code.SUCCESS.d, 200


class {{title_lower | to_pascal_case }}List(Resource):
    """Creation and get_all

    ---
    get:
      tags:
        - api
      responses:
        200:
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/PaginatedResult'
                  - type: object
                    properties:
                      results:
                        type: array
                        items:
                          $ref: '#/components/schemas/{{title_lower | to_pascal_case }}Schema'
    post:
      tags:
        - api
      requestBody:
        content:
          application/json:
            schema:
              {{title_lower | to_pascal_case }}Schema
      responses:
        201:
          content:
            application/json:
              schema:
                type: object
                properties:
                  msg:
                    type: string
                    example: {{title_lower}} created
                  {{title_lower}}: {{title_lower | to_pascal_case }}Schema
    """
    method_decorators = [jwt_required]

    def get(self):
        schema = {{title_lower | to_pascal_case }}Schema(unknown=True, many=True)
        query = {{title_lower | to_pascal_case }}.query. \
            with_entities({% for col in columns%}{{title_lower | to_pascal_case }}.{{col.name |lower}}, {% endfor %})
        req = request.args
        {% for col in columns%}
        {{col.name }} = req.get('{{col.name | to_camel_case}}'){% endfor %}
        {% for col in columns%}
        if {{col.name}}:
            query = query.filter({{title_lower | to_pascal_case }}.{{col.name |lower}} == {{col.name}}){% endfor %}
        data = paginate(query, schema)
        return return_code.SUCCESS.set_data(data).d, 200

    def post(self):
        schema = {{title_lower | to_pascal_case }}Schema(unknown=True, many=True)
        {{title_lower}}s = schema.load(request.json)
        for {{title_lower}} in {{title_lower}}s:
            {{title_lower}}.updated_by = current_user.id
            {{title_lower}}.org_code = current_user.org_code
        db.session.add_all({{title_lower}}s)
        db.session.flush()

        return return_code.SUCCESS.d, 200


@{{title_lower}}_bp.route('/{{title_lower}}s/list', methods=['POST'])
@jwt_required
def query_list():
    schema = {{title_lower | to_pascal_case }}Schema(unknown=True, many=True)
    req = request.json
    {% for col in columns%}
    {{col.name }} = req.get('{{col.name | to_camel_case}}'){% endfor %}
    sort = req.get("sort", None)
    query = {{title_lower | to_pascal_case }}.query. \
        with_entities({% for col in columns%}{{title_lower | to_pascal_case }}.{{col.name |lower}}, {% endfor %})
    {% for col in columns%}
    if {{col.name}}:
        query = query.filter({{title_lower | to_pascal_case }}.{{col.name |lower}} == {{col.name}}){% endfor %}
    if sort:
        query = query.order_by(text(sort))
    data = schema.dump(query.all())
    return return_code.SUCCESS.set_data(data).d, 200


{%- if cookiecutter.use_excel == "yes" %}
@{{title_lower}}_bp.route('/{{title_lower}}s/export', methods=['POST'])
@jwt_required
def export_excel():
    query_sets = {{title_lower | to_pascal_case }}.query.all()
    column_names = [{%for col in columns%}'{{col.name }}', {%endfor %}]
    colnames = [{%for col in columns%}'{{col.comment }}', {%endfor %}]
    return excel.make_response_from_query_sets(query_sets, column_names, file_type="xlsx",
                                               file_name='{{tb_obj.comment or tb_obj.info}}', sheet_name='{{tb_obj.comment or tb_obj.info}}', colnames=colnames)


@{{title_lower}}_bp.route('/{{title_lower}}s/import', methods=['POST'])
@jwt_required
def import_excel():
    session = db.session
    try:
        column_names = [{%for col in columns%}'{{col.name }}', {%endfor %}]
        records = request.get_records(field_name='file', name_columns_by_row=-1, start_row=1, auto_detect_int=False, colnames=column_names)
        db_util.increment_update(session=session,
                                 data_dict_list=records,
                                 schema_type={{title_lower | to_pascal_case }}Schema,
                                 is_src=False,
                                 request_id=current_user.id)
        session.flush()
    except BaseException as e:
        logger.exception(e)
        return return_code.UNKNOWN_ERROR.set_data(e.args).d
    return return_code.SUCCESS.d, 200
{\%- endif %}
